/**
 * @Author: lena
 * @Description:使用redigo操作redis
 * @Version: 1.0.0
 * @Date: 2021/9/17 15:05
 */

package redigo

import (
	"fmt"
	"time"

	"github.com/garyburd/redigo/redis"
)

// 连接
func ConnRedis1() {
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("conn err :", err)
		return
	}
	defer conn.Close()
	fmt.Println(conn) // 输出的是conn的套接字
}

// string操作
func String() (int, error) {
	// 连接
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		return 0, err
	}
	defer conn.Close()
	// set值
	_, err = conn.Do("set", "id", 1001)
	if err != nil {
		return 0, err
	}
	// get值
	res, err := redis.Int(conn.Do("get", "id"))
	if err != nil {
		return 0, err
	}
	return res, nil
}

// hash操作：hset+hget
func Hash1() {
	// 连接
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("conn err :", err)
		return
	}
	defer conn.Close()
	// hset
	_, err = conn.Do("hset", "stu1", "name", "lena")
	if err != nil {
		fmt.Println("hset err :", err)
		return
	}
	_, err = conn.Do("hset", "stu1", "age", 10)
	if err != nil {
		fmt.Println("hset err :", err)
		return
	}
	// hget
	name, err := redis.String(conn.Do("hget", "stu1", "name"))
	if err != nil {
		fmt.Println("hget name err :", err)
		return
	}
	fmt.Println("name =", name)
	age, err := redis.Int(conn.Do("hget", "stu1", "age"))
	if err != nil {
		fmt.Println("hget age err :", err)
		return
	}
	fmt.Println("age =", age)
}

// hash批量操作：hmset+hmget
func Hash2() {
	// 连接
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("conn err :", err)
		return
	}
	defer conn.Close()
	// hmset
	_, err = conn.Do("hmset", "stu2", "name", "lena", "age", 20, "school", "仲恺农业工程学院")
	if err != nil {
		fmt.Println("hmset err :", err)
		return
	}
	// hmget：用strings接收多个结果
	r, err := redis.Strings(conn.Do("hmget", "stu2", "name", "school", "age"))
	if err != nil {
		fmt.Println("hmget err :", err)
		return
	}
	fmt.Printf("type = %T\n", r) // type = []string
	for _, value := range r {
		fmt.Println(value)
	}
}

// list操作
func List() {
	// 连接
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("conn err :", err)
		return
	}
	defer conn.Close()
	// lpush
	_, err = conn.Do("lpush", "list", 1, 2, 3, 4, 5)
	if err != nil {
		fmt.Println("lpush err :", err)
		return
	}
	// lpop
	res, err := redis.Int(conn.Do("lpop", "list"))
	if err != nil {
		fmt.Println("lpop err :", err)
		return
	}
	fmt.Println("lpop =", res) // lpop = 5

	// rpush
	_, err = conn.Do("rpush", "list", 10, 20)
	if err != nil {
		fmt.Println("rpush err :", err)
		return
	}
	// rpop
	res, err = redis.Int(conn.Do("rpop", "list"))
	if err != nil {
		fmt.Println("rpop err :", err)
		return
	}
	fmt.Println("rpop =", res) // rpop = 20
}

// 设置有效时间
func SetTimeOut() {
	// 连接
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("conn err :", err)
		return
	}
	defer conn.Close()
	// set值
	_, err = conn.Do("set", "id", 1001)
	if err != nil {
		fmt.Println("set err :", err)
		return
	}
	// 设置过期时间
	_, err = conn.Do("expire", "id", 5)
	if err != nil {
		fmt.Println("set expire err :", err)
		return
	}
	// get值
	res, err := redis.Int(conn.Do("get", "id"))
	if err != nil {
		fmt.Println("get1 err :", err)
		return
	}
	fmt.Println("data =", res) // data = 1001
	time.Sleep(time.Second * 5)
	res, err = redis.Int(conn.Do("get", "id"))
	if err != nil {
		fmt.Println("get2 err :", err) // get2 err : redigo: nil returned
		return
	}
	fmt.Println("data =", res)
}

// 连接池的使用
var pool *redis.Pool // 定义
func RedisPool() {
	// 初始化
	pool = &redis.Pool{
		MaxIdle:     8,   // 最大空闲链接数
		MaxActive:   0,   // 和数据库的最大链接数，0表示没有限制。（当数据有并发问题的时候需要考虑）
		IdleTimeout: 100, // 最大空闲时间
		Dial: func() (redis.Conn, error) { // 初始化链接代码，指明要连接的协议，IP，端口号
			return redis.Dial("tcp", "127.0.0.1:6379")
		},
	}
	// 从连接池中取出一个链接
	conn := pool.Get()
	defer conn.Close() // 应用程序必须关闭返回的连接：回收方法是activeConn中的Close
	// 操作redis
	conn.Do("set", "pool", "success")
	// 关闭连接池：一旦关闭后不能够再取出链接
	pool.Close()
}
